import os

from django.conf import settings
from django.template import loader

from celery_tasks.main import app
from goods.models import SKU
from MeiduoMall.utils.goods_category import get_goods_category


@app.task(name='generate_static_sku_detail_html')
def generate_static_sku_detail_html(sku_id):
    """
    生成静态商品详情页面
    :param sku_id: 商品sku id
    :return:
    """
    # 查询商品分类菜单
    categories = get_goods_category()

    # 获取当前sku信息,并将对应的图片保存到sku对象中
    sku = SKU.objects.get(id=sku_id)
    sku.images = sku.skuimage_set.all()  # 同一sku商品下可能有多张图片展示/甚至视频(视频是啥字段呢?)

    # 面包屑导航信息中的频道(即详情页中该商品sku的导航:一级--二级--三级,如手机--通讯--手机)
    goods = sku.goods  # 获得该sku对应的spu
    goods.channel = goods.category1.goodschannel_set.all()[0]  # 该spu所对应的一级分类所对应的商品频道

    # 构建当前商品的规格键
    # sku_key = [规格1参数id, 规格2参数id, ...]  注意: 这里此列表的索引和值都是一样的/都是规格id,后面会把值修改的
    sku_specs = sku.skuspecification_set.order_by('spec_id')  # 该商品的具体规格
    sku_key = []
    for spec in sku_specs:
        sku_key.append(spec.option.id)  # 以列表形式展示该商品的具体规格参数

    # 获取当前商品对应SPU的所有SKU
    skus = goods.sku_set.all()

    # 构建当前SPU下不同规格参数(选项)的sku字典
    """
    spec_sku_map = {
        (规格1参数id, 规格2参数id, 规格3参数id, ...): sku_id,
        (规格1参数id, 规格2参数id, 规格3参数id, ...): sku_id,
        ...
    }
    """
    spec_sku_map = {}
    for s in skus:
        # 获取sku的规格参数
        s_specs = s.skuspecification_set.order_by('spec_id')
        # 用于形成规格参数-sku字典的键
        key = []
        for spec in s_specs:
            key.append(spec.option.id)
        # 向规格参数-sku字典添加记录, 由于是同一SPU下的sku,因此规格参数不一样,不然就是同一sku了
        spec_sku_map[tuple(key)] = s.id

    # 获取当前商品的规格信息
    """
    specs = [
       {
           'name': '屏幕尺寸',
           'options': [
               {'value': '13.3寸', 'sku_id': xxx},
               {'value': '15.4寸', 'sku_id': xxx},
           ]
       },
       {
           'name': '颜色',
           'options': [
               {'value': '银色', 'sku_id': xxx},
               {'value': '黑色', 'sku_id': xxx}
           ]
       },
       ...
    ]
    """
    specs = goods.goodsspecification_set.order_by('id')

    # 若当前sku的规格信息不完整,则不再继续
    if len(sku_key) < len(specs):
        return
    for index, spec in enumerate(specs):
        # 复制当前sku的规格键
        key = sku_key[:]  # [规格1参数id, 规格2参数id, ...]  注意: 这里此列表的索引和值都是一样的/都是规格id
        # 该规格的所有选项
        options = spec.specificationoption_set.all()
        # 将SPU下各sku所对应的规格(存在key中)存入option对象(规格选项对象)中
        for option in options:
            # 在规格参数sku字典中查找符合当前规格的sku,且给规格赋规格选项id值
            key[index] = option.id
            # 将SPU下各sku所对应的规格(存在key中)存入option对象(规格选项对象)中
            option.sku_id = spec_sku_map.get(tuple(key))
        spec.option = options

    # 渲染模板,生成静态html文件
    context = {
        'categories': categories,
        'goods': goods,
        'specs': specs,
        'sku': sku
    }
    template = loader.get_template('detail.html')
    html_text = template.render(context)
    file_path = os.path.join(settings.GENERATED_STATIC_HTML_FILES_DIR, 'goods/' + str(sku_id) + '.html')
    with open(file_path, 'w') as f:
        f.write(html_text)
